#ifndef __OS_API_H__
#define __OS_API_H__

#include "gbl_types.h"

/*****************************************************************************
 * OSA Constants
 ****************************************************************************/
#define OS_TIMER_DEAD 0
#define OS_TIMER_CREATED 1
#define OS_TIMER_ACTIVE 2
#define OS_TIMER_INACTIVE 3

#define OS_LOWEST_PRIORITY 252
#define OS_HIGHEST_PRIORITY 3
#define OS_MIN_STACK_SIZE 256
#define OS_APP_PRIORITY 150

#define OS_SUSPEND 0xFFFFFFFF
#define OS_NO_SUSPEND 0
#define OS_FLAG_AND 5
#define OS_FLAG_AND_CLEAR 6
#define OS_FLAG_OR 7
#define OS_FLAG_OR_CLEAR 8
#define OS_FIXED 9
#define OS_VARIABLE 10
#define OS_FIFO 11
#define OS_PRIORITY 12
#define OS_GLOBAL 13
#define OS_OS_INDEPENDENT 14

#define OSA_TICK_FREQ_IN_MILLISEC 5

/*========================================================================
 *  OSA Return Error Codes
 *========================================================================*/

enum
{
    OS_SUCCESS = 0,      /* 0x0 -no errors                                        */
    OS_FAIL,             /* 0x1 -operation failed code                            */
    OS_TIMEOUT,          /* 0x2 -Timed out waiting for a resource                 */
    OS_NO_RESOURCES,     /* 0x3 -Internal OS resources expired                    */
    OS_INVALID_POINTER,  /* 0x4 -0 or out of range pointer value                  */
    OS_INVALID_REF,      /* 0x5 -invalid reference                                */
    OS_INVALID_DELETE,   /* 0x6 -deleting an unterminated task                    */
    OS_INVALID_PTR,      /* 0x7 -invalid memory pointer                           */
    OS_INVALID_MEMORY,   /* 0x8 -invalid memory pointer                           */
    OS_INVALID_SIZE,     /* 0x9 -out of range size argument                       */
    OS_INVALID_MODE,     /* 0xA, 10 -invalid mode                                 */
    OS_INVALID_PRIORITY, /* 0xB, 11 -out of range task priority                   */
    OS_UNAVAILABLE,      /* 0xC, 12 -Service requested was unavailable or in use  */
    OS_POOL_EMPTY,       /* 0xD, 13 -no resources in resource pool                */
    OS_QUEUE_FULL,       /* 0xE, 14 -attempt to send to full messaging queue      */
    OS_QUEUE_EMPTY,      /* 0xF, 15 -no messages on the queue                     */
    OS_NO_MEMORY,        /* 0x10, 16 -no memory left                              */
    OS_DELETED,          /* 0x11, 17 -service was deleted                         */
    OS_SEM_DELETED,      /* 0x12, 18 -semaphore was deleted                       */
    OS_MUTEX_DELETED,    /* 0x13, 19 -mutex was deleted                           */
    OS_MSGQ_DELETED,     /* 0x14, 20 -msg Q was deleted                           */
    OS_MBOX_DELETED,     /* 0x15, 21 -mailbox Q was deleted                       */
    OS_FLAG_DELETED,     /* 0x16, 22 -flag was deleted                            */
    OS_INVALID_VECTOR,   /* 0x17, 23 -interrupt vector is invalid                 */
    OS_NO_TASKS,         /* 0x18, 24 -exceeded max # of tasks in the system       */
    OS_NO_FLAGS,         /* 0x19, 25 -exceeded max # of flags in the system       */
    OS_NO_SEMAPHORES,    /* 0x1A, 26 -exceeded max # of semaphores in the system  */
    OS_NO_MUTEXES,       /* 0x1B, 27 -exceeded max # of mutexes in the system     */
    OS_NO_QUEUES,        /* 0x1C, 28 -exceeded max # of msg queues in the system  */
    OS_NO_MBOXES,        /* 0x1D, 29 -exceeded max # of mbox queues in the system */
    OS_NO_TIMERS,        /* 0x1E, 30 -exceeded max # of timers in the system      */
    OS_NO_MEM_POOLS,     /* 0x1F, 31 -exceeded max # of mem pools in the system   */
    OS_NO_INTERRUPTS,    /* 0x20, 32 -exceeded max # of isr's in the system       */
    OS_FLAG_NOT_PRESENT, /* 0x21, 33 -requested flag combination not present      */
    OS_UNSUPPORTED,      /* 0x22, 34 -service is not supported by the OS          */
    OS_NO_MEM_CELLS,     /* 0x23, 35 -no global memory cells                      */
    OS_DUPLICATE_NAME,   /* 0x24, 36 -duplicate global memory cell name           */
    OS_INVALID_PARM      /* 0x25, 37 -invalid parameter                           */
};

/*****************************************************************************
 * OSA Data Types
 ****************************************************************************/
typedef void *OSTaskRef;
typedef void *OSHISRRef;
typedef void *OSSemaRef;
typedef void *OSMutexRef;
typedef void *OSMsgQRef;
typedef void *OSTimerRef;
typedef void *OSFlagRef;
typedef UINT8 OS_STATUS;
typedef void *OS_HISR;

/*========================================================================
 *  OSA Task Management:
 *========================================================================*/

extern OS_STATUS OSATaskCreate(
    OSTaskRef *taskRef,        /* OS task reference                       */
    void *stackPtr,            /* pointer to start of task stack area     */
    UINT32 stackSize,          /* number of bytes in task stack area      */
    UINT8 priority,            /* task priority 0 - 31                    */
    CHAR *taskName,            /* task name                               */
    void (*taskStart)(void *), /* pointer to task entry point        */
    void *argv                 /* task entry argument pointer             */
);

extern OS_STATUS OSATaskDelete(OSTaskRef taskRef);

extern OS_STATUS OSATaskSuspend(OSTaskRef taskRef);

extern OS_STATUS OSATaskResume(OSTaskRef taskRef);

extern void OSATaskSleep(UINT32 ticks); /* time to sleep in ticks        */

extern OS_STATUS OSATaskChangePriority(
    OSTaskRef taskRef, /* OS task reference                       */
    UINT8 newPriority, /* new task priority                       */
    UINT8 *oldPriority /* old task priority                       */
);

extern OS_STATUS OSATaskGetPriority(
    OSTaskRef taskRef, /* OS task reference                       */
    UINT8 *priority    /* task priority                           */
);

extern OS_STATUS OSATaskGetStatus(OSTaskRef taskRef);

extern OS_STATUS OSATaskGetCurrentRef(OSTaskRef *taskRef); /* Get current running task ref  */

extern void OSATaskYield(void); /* Allow other ready tasks to run          */

/*========================================================================
 *  OSA Sys Context info
 *========================================================================*/
extern OS_STATUS OSAContextLock(void);
extern OS_STATUS OSAContextUnlock(void);

/*========================================================================
 *  OSA Semaphore Management
 *========================================================================*/

extern OS_STATUS OSASemaphoreCreate(
    OSSemaRef *semaRef,  /* OS semaphore reference                     */
    UINT32 initialCount, /* initial count of the semaphore             */
    UINT8 waitingMode    /* mode of tasks waiting OS_FIFO, OS_PRIORITY */
);

extern OS_STATUS OSASemaphoreAcquire(
    OSSemaRef semaRef, /* OS semaphore reference                   */
    UINT32 timeout     /* OS_SUSPEND, OS_NO_SUSPEND, or timeout    */
);

extern OS_STATUS OSASemaphorePoll(
    OSSemaRef semaRef, /* OS semaphore reference                   */
    UINT32 *count      /* Current semaphore count                  */
);

extern OS_STATUS OSASemaphoreRelease(OSSemaRef semaRef);

extern OS_STATUS OSASemaphoreDelete(OSSemaRef semaRef);

/*========================================================================
 *  OSA Mutex Management
 *========================================================================*/

extern OS_STATUS OSAMutexCreate(
    OSMutexRef *mutexRef, /* OS mutex reference                         */
    UINT8 waitingMode     /* mode of tasks waiting OS_FIFO, OS_PRIORITY */
);

extern OS_STATUS OSAMutexLock(
    OSMutexRef mutexRef, /* OS mutex reference                       */
    UINT32 timeout       /* OS_SUSPEND, OS_NO_SUSPEND, or timeout    */
);

extern OS_STATUS OSAMutexUnlock(OSMutexRef mutexRef);

extern OS_STATUS OSAMutexDelete(OSMutexRef mutexRef);

/*========================================================================
 *  OSA Message Passing
 *========================================================================*/

extern OS_STATUS OSAMsgQCreate(
    OSMsgQRef *msgQRef, /* OS message queue reference              */
    char *queueName,    /* name of message queue                   */
    UINT32 maxSize,     /* max message size the queue supports     */
    UINT32 maxNumber,   /* max # of messages in the queue          */
    UINT8 waitingMode   /* mode of tasks waiting OS_FIFO, OS_PRIORITY */
);

extern OS_STATUS OSAMsgQSend(
    OSMsgQRef msgQRef, /* message queue reference                 */
    UINT32 size,       /* size of the message                     */
    UINT8 *msgPtr,     /* start address of the data to be sent    */
    UINT32 timeout     /* OS_SUSPEND, OS_NO_SUSPEND, or timeout   */
);

extern OS_STATUS OSAMsgQRecv(
    OSMsgQRef msgQRef, /* message queue reference                 */
    UINT8 *recvMsg,    /* pointer to the message received         */
    UINT32 size,       /* size of the message                     */
    UINT32 timeout     /* OS_SUSPEND, OS_NO_SUSPEND, or timeout   */
);

extern OS_STATUS OSAMsgQPoll(
    OSMsgQRef msgQRef, /* message queue reference                 */
    UINT32 *msgCount   /* number of messages on the queue         */
);

extern OS_STATUS OSAMsgQDelete(OSMsgQRef msgQRef);

/*========================================================================
 *  OSA Event Management:
 *========================================================================*/

extern OS_STATUS OSAFlagCreate(
    OSFlagRef *flagRef /* OS reference to the flag                */
);

extern OS_STATUS OSAFlagWait(
    OSFlagRef flagRef, /* OS reference to the flag                */
    UINT32 mask,       /* flag mask to wait for                   */
    UINT32 operation,  /* OSA_FLAG_AND, OSA_FLAG_AND_CLEAR,       */
                       /* OSA_FLAG_OR, OSA_FLAG_OR_CLEAR          */
    UINT32 *flags,     /* Current value of all flags              */
    UINT32 timeout     /* OS_SUSPEND, OS_NO_SUSPEND, or timeout   */
);

extern OS_STATUS OSAFlagSet(
    OSFlagRef flagRef, /* OS reference to the flag                */
    UINT32 mask,       /* flag mask                               */
    UINT32 operation   /* OSA_FLAG_AND, OSA_FLAG_OR               */
);

extern OS_STATUS OSAFlagDelete(OSFlagRef flagRef);

/*========================================================================
 *  OSA Timer Management:
 *========================================================================*/
typedef struct
{
    UINT32 status;      /* timer status OS_ENABLED, OS_DISABLED    */
    UINT32 expirations; /* number of expirations for cyclic timers */
} OSATimerStatus;

extern OS_STATUS OSATimerCreate(OSTimerRef *timerRef);

extern OS_STATUS OSATimerStart(
    OSTimerRef timerRef,             // OS supplied timer reference
    UINT32 initialTime,              //  [IN]    Initial expiration time in clock ticks
    UINT32 rescheduleTime,           //  [IN]    Periodic expiration time in clock ticks. 0=One shot timer
    void (*callBackRoutine)(UINT32), //  [IN]    Routine to call when timer expiers
    UINT32 timerArgc                 //  [IN]    Argument to be passed to the callBackRoutine
);

extern OS_STATUS OSATimerGetStatus(
    OSTimerRef timerRef,        /* timer reference                     */
    OSATimerStatus *timerStatus /* timer status information            */
);

extern OS_STATUS OSATimerStop(OSTimerRef timerRef);
extern OS_STATUS OSATimerDelete(OSTimerRef timerRef);

/*===========================================================================
 *  OSA Real-Time Access:
 *=========================================================================*/

#define SEC2TICKS(sec) ((sec) * 200)
#define MS2TICKS(ms) (((ms)) / OSA_TICK_FREQ_IN_MILLISEC)

#define sleep(x) OSATaskSleep((x) * 200)                                                          // second
#define msleep(x) OSATaskSleep((x) < OSA_TICK_FREQ_IN_MILLISEC? 1 : (x) / OSA_TICK_FREQ_IN_MILLISEC) // millisecond

extern UINT32 OSAGetTicks(void);

/*========================================================================
 *  HISR Management:
 *========================================================================*/
#define HISR_PRIORITY_0 0 // highest priority
#define HISR_PRIORITY_1 1 // medium priority
#define HISR_PRIORITY_2 2 // lowest priority

void Os_Create_HISR(OS_HISR *hisr, char *name, VOID (*hisr_entry)(VOID), unsigned char priority);
INT32 Os_Activate_HISR(OS_HISR *hisr);
INT32 Os_Delete_HISR(OS_HISR *hisr);

#define OS_Create_HISR Os_Create_HISR /*call for NU_Create_HISR*/
#define OS_Activate_HISR Os_Activate_HISR
#define OS_Delete_HISR Os_Delete_HISR

UINT32 OsaGetDefaultMemPoolTotalSize(void);
UINT32 OsaGetDefaultMemPoolFreeSize(void);

#endif /* __OS_API_H__ */
